package com.cooperate.fly.controller;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.cooperate.fly.bo.DataRight;
import com.cooperate.fly.bo.Schema;
import com.cooperate.fly.bo.User;
import com.cooperate.fly.mapper.DataRightMapper;
import com.cooperate.fly.mapper.SchemaMapper;
import com.cooperate.fly.mapper.UserMapper;
import com.cooperate.fly.service.buildDB.BuildFieldService;
import com.cooperate.fly.service.buildDB.BuildSchemaService;
import com.cooperate.fly.util.SystemConstant;
import com.cooperate.fly.web.Result;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

@Controller
@RequestMapping("/schema")
@SessionAttributes(SystemConstant.USER_SESSION_KEY)
public class BuildSchemaController extends BaseController {
	@Resource
	private BuildSchemaService buildSchemaService;

	@Resource
	private BuildFieldService buildFieldService;

	@Autowired
	private SchemaMapper schemaMapper;

	@Autowired
	private UserMapper userMapper;

	@Autowired
	private DataRightMapper dataRightMapper;

	@Value("#{propertiesReader['dReadAuth']}")
	private int readAuth;

	@Value("#{propertiesReader['dWriteAuth']}")
	private int writeAuth;

	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public String listAll(Model model) {
		model.addAttribute("schemaData", buildSchemaService.loadSchema());
		return "schema-design";
	}

	@RequestMapping(value = "/create", method = RequestMethod.GET)
	@ResponseBody
	public Result add(
			@RequestParam(value = "name", required = true) String name,
			@RequestParam(value = "type", required = true) int type,
			@RequestParam(value = "parentId", required = true) int parentId) {
		Schema schema = new Schema();
		schema.setName(name);
		schema.setType(type);
		schema.setParentId(parentId);
		return buildSchemaService.createSchemaNode(schema);
	}

	@RequestMapping(value = "/update", method = RequestMethod.GET)
	@ResponseBody
	public Result update(Schema schema) {
		// update
		return buildSchemaService.updateSchemaNode(schema);
	}

	// if node is catalog, then delete all the son node
	@RequestMapping(value = "/delete")
	@ResponseBody
	public Result delete(@RequestParam(value = "id", required = true) int id) {
		return buildSchemaService.deleteSchemaNode(id);
	}

	@RequestMapping(value = "/setDatabase")
	@ResponseBody
	public Result setDatabase(
			@RequestParam(value = "id", required = true) int id) {
		return buildSchemaService.setDatabase(id);
	}

	// the interface of get data
	@RequestMapping(value = "/name/{schemaNames}", produces = "application/json;charset=utf-8", method = RequestMethod.GET, params = "action=get")
	@ResponseBody
	public String getSchema(@PathVariable String schemaNames) {
		return buildSchemaService.parseSchemaUrl(schemaNames);
	}

	@RequestMapping(value = "/name/{schemaNames}/field/name/{fieldNames}", produces = "application/json;charset=utf-8", method = RequestMethod.GET, params = "action=get")
	@ResponseBody
	public String getField(@PathVariable String schemaNames,
			@PathVariable String fieldNames) {
		return buildFieldService.parseFieldUrl(schemaNames, fieldNames);
	}

	@ResponseBody
	@RequestMapping("/getSchemaRemark3")
	public Result getSchemaRemark3(int id) {
		return buildSchemaService.getSchemaRemark3(id);
	}

	@ResponseBody
	@RequestMapping("/getSchemaInfo")
	public Result getSchemaInfo(int id) {
		// info包括remark2图片说明和remark3的文字说明
		return buildSchemaService.getSchemaInfo(id);
	}

	@ResponseBody
	@RequestMapping("/setSchemaRemark3")
	public Result getSchemaRemark3(int id, String remark3) {
		return buildSchemaService.setSchemaRemark3(id, remark3);
	}

	/**
	 * schemaDescribePic文件夹中通过schemaId来进行描述图片的存储
	 * 
	 * @param schemaId
	 * @param multipartRequest
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	@ResponseBody
	@RequestMapping(value = "/savePicture", method = RequestMethod.POST)
	public void savePicture(
			@RequestParam(value = "schemaId", required = true) int schemaId,
			MultipartHttpServletRequest multipartRequest,
			HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		response.setContentType("text/html;charset=UTF-8");
		int resultCode = 500;
		try {
			for (Iterator it = multipartRequest.getFileNames(); it.hasNext();) {
				String key = (String) it.next();
				MultipartFile file = multipartRequest.getFile(key);
				if (!file.isEmpty()) {
					String postfix = file.getOriginalFilename().substring(
							file.getOriginalFilename().lastIndexOf('.'));
					String fileName = file.getOriginalFilename().substring(0,
							file.getOriginalFilename().lastIndexOf('.'));
					if (fileName.length() > 490) {
						return;// 名字不能够大于存储的空间
					}
					String filePath = request.getSession().getServletContext()
							.getRealPath("/")
							+ "schemaDescribePic" + File.separator;
					File pathFile = new File(filePath);
					if (!pathFile.exists()) {
						pathFile.mkdirs();
					}
					// 后台存储的时候加上schemaId来唯一标记，也可以加上时间戳
					File tempFile = new File(filePath + fileName + "_"
							+ schemaId + postfix);
					if (tempFile.exists()) {
						tempFile.delete();// 如果之前存在描述图片则删除进行更新
					}
					OutputStream out = new FileOutputStream(tempFile);
					// 名字不能够超过500个字符
					Schema schema = schemaMapper.selectByPrimaryKey(schemaId);
					schema.setRemark2(fileName + "_" + schemaId + postfix);
					schemaMapper.updateByPrimaryKey(schema);
					out.write(file.getBytes());
					out.close();
					resultCode = 200;
				}
			}
			response.getWriter().print(resultCode);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 加载待分配权限的用户
	 * 
	 * @return
	 */
	@RequestMapping(value = "/loadAuthUsers", produces = "application/json;charset=utf-8")
	@ResponseBody
	public List<User> loadAuthUsers(int id) {
		List<User> users = userMapper.selectAll();
		List<User> result = new ArrayList<User>();
		for (User user : users) {
			// 超级用户和数据策划者不在这个名单中
			if (user.getRoleId() > 2) {
				result.add(user);
			}
		}
		return result;
	}

	/**
	 * 加载待分配权限的用户
	 * 
	 * @return
	 */
	@RequestMapping(value = "/loadReadUsers", produces = "application/json;charset=utf-8")
	@ResponseBody
	public List loadReadUsers(int schemaId) {
		List<DataRight> temp = dataRightMapper.selectBySchemaAndType(schemaId,
				readAuth);
		List<User> users = new ArrayList<User>();
		for (DataRight dr : temp) {
			users.add(userMapper.selectByPrimaryKey(dr.getUserid()));
		}
		return users;
	}

	/**
	 * 加载待分配权限的用户
	 * 
	 * @return
	 */
	@RequestMapping(value = "/loadWriteUsers", produces = "application/json;charset=utf-8")
	@ResponseBody
	public List loadWriteUsers(int schemaId) {
		List<DataRight> temp = dataRightMapper.selectBySchemaAndType(schemaId,
				writeAuth);
		List<User> users = new ArrayList<User>();
		for (DataRight dr : temp) {
			users.add(userMapper.selectByPrimaryKey(dr.getUserid()));
		}
		return users;
	}

	/**
	 * 加载待分配权限的用户
	 * 
	 * @return
	 */
	@RequestMapping(value = "/saveAuthUsers", produces = "application/json;charset=utf-8")
	@ResponseBody
	public Result saveAuthUsers(int databaseId, String readIds, String writeIds) {
		Result result = new Result();
		result.setSuccessful(false);
		ArrayList<DataRight> oldReadIds = dataRightMapper
				.selectBySchemaAndType(databaseId, readAuth);
		ArrayList<DataRight> oldWriteIds = dataRightMapper
				.selectBySchemaAndType(databaseId, writeAuth);
		// 对读用户权限处理
		Set<Integer> rIdsList = new Gson().fromJson(readIds,
				new TypeToken<HashSet<Integer>>() {
				}.getType());
		Set<Integer> wIdsList = new Gson().fromJson(writeIds,
				new TypeToken<HashSet<Integer>>() {
				}.getType());
		if (rIdsList == null) {
			rIdsList = new HashSet<Integer>();
		}
		if (wIdsList == null) {
			wIdsList = new HashSet<Integer>();
		}
		Set<Integer> rDeleteList = new HashSet<Integer>();
		Set<Integer> wDeleteList = new HashSet<Integer>();
		for (DataRight dr : oldReadIds) {
			if (rIdsList.contains(dr.getUserid())) {
				rIdsList.remove(dr.getUserid());
			} else {
				rDeleteList.add(dr.getId());
			}
		}
		for (Integer rid : rIdsList) {
			DataRight dataRight = new DataRight();
			dataRight.setSchemaid(databaseId);
			dataRight.setType(readAuth);
			dataRight.setUserid(rid);
			dataRightMapper.insert(dataRight);
		}
		for (Integer id : rDeleteList) {
			dataRightMapper.deleteByPrimaryKey(id);
		}

		for (DataRight dr : oldWriteIds) {
			if (wIdsList.contains(dr.getUserid())) {
				wIdsList.remove(dr.getUserid());
			} else {
				wDeleteList.add(dr.getId());
			}
		}
		for (Integer wid : wIdsList) {
			DataRight dataRight = new DataRight();
			dataRight.setSchemaid(databaseId);
			dataRight.setType(writeAuth);
			dataRight.setUserid(wid);
			dataRightMapper.insert(dataRight);
		}

		for (Integer id : wDeleteList) {
			dataRightMapper.deleteByPrimaryKey(id);
		}
		result.setSuccessful(true);
		return result;
	}
}
